//
//  main.m
//  08-iOS9新特性(Nullability, 范型，_kindof)
//
//  Created by dllo on 16/7/13.
//  Copyright © 2016年 dllo. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Truck.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
    Person *per = [[Person alloc] init];
 // 1.nullability
   // nonnull 修饰的属性 对应的getter 和 setter
    NSString *objc = nil;
    per.name = objc;
    [per setName:nil];
    per.name = @"zhangsan";
    [per name];
   
   // nullable 修饰的属性， 对应得getter和setter方法
   // [per setSex:<#(NSString * _Nullable)#>];
   // [per sex];
    per.sex = nil;
    
    
//    [per setSex:<#(NSString * _Nullable)#>]
//    [per friends]
    
//    [per setDic:<#(NSDictionary * _Nonnull)#>]

    
    //泛型
    // 带泛型的容器(规定了容器中所存储的类型)
    // 1. 数组中添加其他类型， 会有警告
    // 2. 数组中取出来的类型不再是id类型， 对应变成声明时的类型
    // 3. 泛型会改变类的一些方法， 使于声明的类型相同
    // 声明一个可变数组， 内部存放的都是NSString
    NSMutableArray<NSString *> *array = [NSMutableArray arrayWithObjects:@"123", nil];
    NSString *string = array.firstObject;
//    [array.firstObject.length];
    [array addObject:@""];
    [array addObject:@20];
    [array addObject:per];
  NSInteger *interger = [array objectAtIndex:0].length;
    
    
    // 带泛型的字典
    NSMutableDictionary<NSString *,NSString *> *dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"于涵", @"namew", nil];
    [dic objectForKey:@"name"].length;
    
   // 自定义泛型
    Truck<Person *> *truckPer = [[Truck alloc] init];
    [truckPer addObject:per];
    
    
    Student *stu = [[Student alloc] init];
    stu.stuNumber = @"0001";
    [truckPer addObject:stu];
    Truck<Student *> *truckStu = [[Truck alloc] init];
    [truckStu addObject:stu];
    [truckStu addObject:per];
    
    
   // 协变    
    Truck *truck = nil;
    Truck<NSArray *> *truck1 = nil;
    Truck<NSMutableArray *> *truck2 = nil;
//    大类型（任意类型） 可以给有泛型的赋值
//    也可以有泛型给它赋值
    truck  = truck1;
    truck = truck2;
    
    truck1 = truck;
    truck2 = truck;
//    __covariant 协变性 子类在给父类赋值时， 自动强转
//  Truck<NSArray *>  Truck<NSMutableArray *>
    truck1 = truck2;
//  __contravariant 逆变 父类在给子类赋值时，自动强转（暂时不知道应用何处）
//    truck2 = truck1;
    
//    3.__kindof
//   加__kindof修饰后， 返回的类型及其子类型， 都可以接收这个返回值
    Truck *truckKindsOf = [[Truck alloc] init];
    NSMutableArray *arr = (NSMutableArray *)[truckKindsOf returnArray];
    NSArray *arr1 = [truckKindsOf returnArray];
    NSMutableArray *arr2 = (NSMutableArray *)arr1;
    
    return 0;
}
